using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace unTroublemaker.Parsing
{
    internal class ParserLoader
    {
        private readonly List<ISpecificationParser> _parsers = new List<ISpecificationParser>();
        private readonly string _error;

        public ParserLoader(Assembly assembly)
        {
            var specificationParserTypes = GetTypesFrom(assembly);

            var failedTypes = new List<string>();
            foreach (var type in specificationParserTypes)
            {
                string error;
                if(!TryInstantiate(type, out error))
                    failedTypes.Add(error);
            }

            if (failedTypes.Any())
                _error = "Failed to instantiate following types: \r\n" + string.Concat("\r\n\r\n", failedTypes);
        }

        private IEnumerable<Type> GetTypesFrom(Assembly assembly)
        {
            foreach (var type in assembly.GetTypes())
                if (type.IsClass && typeof (ISpecificationParser).IsAssignableFrom(type) && type != typeof(SpecificationParser))
                    yield return type;
        }

        private bool TryInstantiate(Type type, out string error)
        {
            try
            {
                error = null;
                Parsers.Add((ISpecificationParser)Activator.CreateInstance(type));
                return true;
            }
            catch (Exception e)
            {
                error = e.Format();
                return false;
            }
        }

        public bool HasErrors { get { return !string.IsNullOrEmpty(_error); } }

        public string Error { get { return _error; } }

        public List<ISpecificationParser> Parsers { get { return _parsers; } } 
    }
}